#ifndef DEF_QUEUE
#define DEF_QUEUE
//#include <pthread.h>

/* nodes type */
typedef struct QueueNod {
	void* data;
	struct QueueNod * next;
		
} QueueNod;

/* queue of QueueNod */
typedef struct {
	struct QueueNod * front;
	struct QueueNod * rear;
	int size;
	pthread_mutex_t mutex;
	pthread_mutex_t mutex_non_empty;
	pthread_cond_t cond_non_empty;
} Queue;

/* queue initialisation */
int queue_init(Queue * queue)
{
	queue->front = queue->rear = NULL;
	queue->size = 0;
	pthread_mutex_init(& (queue->mutex), NULL);
	pthread_mutex_init(& (queue->mutex_non_empty), NULL);
	pthread_cond_init(& (queue->cond_non_empty), NULL);
}

/* get queue size */
int queue_size(Queue *queue)
{
    return queue->size;
}

/* enqueue one data elt */
int queue_enqueue(Queue * queue, void * newElt)
{
	/* create a new QueueNod */
	QueueNod * newNod = malloc(sizeof(QueueNod));
	
	if (newNod == NULL)
	{
		return EXIT_FAILURE;
	}
	
	newNod->data = newElt;
	newNod->next = NULL;
	
	/* case when queue is empty */
	if(queue->size == 0)
	{
		queue->front = newNod;
		queue->rear = newNod;
		queue->size++;
		return EXIT_SUCCESS;
	}
	
	/* add at end of queue */
	queue->rear->next = newNod;
	queue->rear = newNod;
	queue->size++;
	
	return EXIT_SUCCESS;
}

/* dequeue one data elt */
int queue_dequeue(Queue * queue, void ** delElt)
{
	void * return_elt;
	QueueNod * tmpNod;
	
	/* case when queue is empty */
	if(queue->front == NULL)
	{
		*delElt = NULL;//or not put anything
		return EXIT_FAILURE;
	}
	
	/* delete from head */
	return_elt = queue->front->data ;
	tmpNod = queue->front;
	queue->front = queue->front->next;
	if(queue->front == NULL) queue->rear = NULL;
	free(tmpNod);

	*delElt = return_elt ;
	queue->size--;
	
	return EXIT_SUCCESS;	
}

/* delete all queue elts (destroy)*/
int queue_clear(Queue * queue)
{
	void * out;
	
	while(queue->front != NULL)
	{
		queue_dequeue(queue, &out);
	}
	
	return EXIT_SUCCESS;
}

/* print queue data elts */
int queue_print(Queue * queue)
{
	QueueNod * tmp;
	int i = 1;
	
	printf(":::: Printing (%d) Elts of queue (%p-%p) :::::\n", queue->size, queue->front, queue->rear);
	
	tmp = queue->front;
	while( tmp != NULL)
	{
		printf(":: Elt %p at %p \n", tmp->data, tmp);
		tmp = tmp->next;
	}
	
	return EXIT_SUCCESS;
}

#endif



